# -*- coding: utf-8 -*-

import asyncio
from datetime import datetime
import functools
import sys

import pandas as pd
import utils
import wqb
from self_correlation import SelfCorrelation

class Submitter:
    def __init__(self
        , wqbs: wqb.WQBSession
        , begin_time:str
        , end_time:str
        , self_corr_threshold:float=0.6
        , sharpe:float = 1.58
        , fitness:float = 1.0
        , submit_num:int=2):
        """
        Args:
            wqbs: WQBSession
            submit_num: 提交个数
            improve: 提升幅度
        """
        self.wqbs = wqbs
        self.self_corr_threshold = self_corr_threshold
        self.submit_num = submit_num
        self.begin_time = begin_time
        self.end_time = end_time
        self.sharpe = sharpe
        self.fitness = fitness
        # self.correlation = SelfCorrelation(wqbs=wqbs)
# 
    def submit(self):
        limit_num = 2000
        alphas = utils.submitable_alphas(
            self.wqbs,
            start_time=self.begin_time,
            end_time=self.end_time,
            sharpe=self.sharpe,
            fitness=self.fitness
            ,limit=limit_num
            , order='is.sharpe',others=['color=BLUE']
        )
        if len(alphas) == 0:
            print('没有可提交的 Alpha...')
            return
        # 过滤掉有FAIL指标的的alpha
        alphas =  utils.filter_failed_alphas(self.wqbs, alphas)
        # 自相关性过滤
        # alphas = self.correlation.filter_correlation(alphas, self.self_corr_threshold)
        if len(alphas) == 0:
            print('过滤没有可提交的 Alpha...')
            return

        print(f'过滤后共 {len(alphas)} 个 Alpha 可提交...')
        alphas = sorted(alphas, key=functools.cmp_to_key(utils.sort_by_grade))
        alpha_ids = []
        for alpha in alphas:
            is_data = alpha['is']
            # if is_data['returns'] <= is_data['turnover']:
            #     continue
            # if self.checkRank:
            
            #     if not utils.is_favorable(wqbs=self.wqbs, alpha_id=alpha['id'], improve=self.improve):
            #         print(f'❌ Alpha {alpha["id"]} 不符合提升{self.improve}名次！')
            #         continue
            #     alpha_ids.append(alpha['id'])
            #     print(f'✅ Alpha {alpha["id"]} 可提升{self.improve}名次！')
            # else:
            #     alpha_ids.append(alpha['id'])
            alpha_ids.append(alpha['id'])
        self.submit_new(alpha_ids)

    def submit_new(self, alpha_ids:list)->list[str]:
        start_time = datetime.now()
        if len(alpha_ids) == 0:
            print('没有可提交的 Alpha...')
        processed_ids = []
        sussess_ids = []
        for alpha_id in alpha_ids:
            if asyncio.run(
                self._submit(
                    alpha_id,
                    log=f'{self.__class__}#submit'
                )
            ):
                sussess_ids.append(alpha_id)
            processed_ids.append(alpha_id)
            if len(sussess_ids) >= self.submit_num:
                break
        print(f'共提交 {len(sussess_ids)} 个 Alpha: {sussess_ids}')
        # 做一次增量下载
        # self.correlation.download_data(flag_increment=True)
        print(f'总耗时: {(datetime.now() - start_time).seconds}秒')
        return processed_ids
            
    
    async def _submit(
        self,
        alpha_id: str,
        log: str | None = '',
        max_tries: int = 500,
    ) -> bool:
        """
        提交 Alpha
        提交返回403就是失败(服务器check不通过)
        """
        start_time = datetime.now()
        print(f'Alpha {alpha_id} 提交中...')
        url = f'{wqb.WQB_API_URL}/alphas/{alpha_id}/submit'
        resp = self.wqbs.post(url, allow_redirects=False)
        if resp.status_code == 303:
            print(f' Alpha {alpha_id} 其它线程提交中...')
            return False
        if resp.status_code == 403:
            self.submit_fail(alpha_id, checks=resp.json()['is']['checks'])
            return False
        # print(f'url: {resp.headers[wqb.LOCATION]}')


        resp = await self.wqbs.retry(
            wqb.GET, url, max_tries=max_tries, log=log
        )
        end_time = datetime.now()
        print(f'Alpha {alpha_id} 提交耗时: {(end_time - start_time).seconds}秒')
        if resp.status_code == 404:
            print(resp.json())
            print(f'❌  Alpha {alpha_id} 提交超时')
            return False
        if resp.status_code == 403:
            self.submit_fail(alpha_id, checks=resp.json()['is']['checks'])
            return False
        if resp.status_code == 200:
            print(f'✅ Alpha {alpha_id} 提交成功！')
            return True
        print(f'❌ Alpha {alpha_id} 提交失败！status_code: {resp.status_code}')
        return False
    
    def submit_fail(self, alpha_id: str, checks:list):
        fail_checks = []
        for check in checks:
            if check['result'] == 'FAIL':
                fail_checks.append(check)
        df = pd.DataFrame(fail_checks)
        self.wqbs.patch_properties(alpha_id,color='RED', log=f'{self.__class__}#submit_fail')
        # print(f'标记:{resp.status_code}')
        print(f'❌ Alpha {alpha_id} 提交失败: \n{df}')


if __name__ == '__main__':
    wqbs= wqb.WQBSession((utils.load_credentials("~/.brain_credentials.txt")), logger=wqb.wqb_logger(name='logs/wqb_' + datetime.now().strftime('%Y%m%d')))
    submitter = Submitter(wqbs, begin_time='2025-06-01', end_time='2025-06-02', submit_num=1)
    asyncio.run(
        submitter._submit(sys.argv[1])
    )